Micron Document
πŸŽ–οΈGitΠ―Ρ€Π°πŸŽ–οΈ


Displaying Raw β€’ Download

feature/node/src/commonTest/kotlin/org/meshtastic/feature/node/metrics/TracerouteChartTest.kt 520fa717a938fd84682403b41f57d9f7e1ef49ef (520fa717) Text, 10.21 KB

T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.feature.node.metrics

Tff7b72import T7ee787okio.ByteString.Companion.toByteString
Tff7b72import T7ee787org.meshtastic.core.model.MeshLog
Tff7b72import T7ee787org.meshtastic.core.model.util.TimeConstants.MS_PER_SEC
Tff7b72import T7ee787org.meshtastic.proto.Data
Tff7b72import T7ee787org.meshtastic.proto.FromRadio
Tff7b72import T7ee787org.meshtastic.proto.MeshPacket
Tff7b72import T7ee787org.meshtastic.proto.PortNum
Tff7b72import T7ee787org.meshtastic.proto.RouteDiscovery
Tff7b72import T7ee787kotlin.test.Test
Tff7b72import T7ee787kotlin.test.assertEquals
Tff7b72import T7ee787kotlin.test.assertNotNull
Tff7b72import T7ee787kotlin.test.assertNull

T8b949e/**
* Tests for [resolveTraceroutePoints] β€” the pure function that pairs traceroute requests with their responses and
* computes hop counts and round-trip duration.
*
* Wire format note: The [RouteDiscovery] proto on the wire contains only **intermediate** hops (not endpoints).
* [MeshPacket.fullRouteDiscovery] prepends the destination and appends the source to produce the full route. For
* `route_back` to be wrapped with endpoints, `hop_start > 0` and `snr_back` must be non-empty.
*/
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffMagicNumberTa5d6ff"Tb4b4b4)
Tff7b72class T56d364TracerouteChartTest Tb4b4b4{

Tff7b72companion Tff7b72object Tb4b4b4{
T8b949e/** Node number for the local (requesting) node. */
Tff7b72private Tff7b72const Tff7b72val Te6edf3LOCAL_NODE Tff7b72= T79c0ff1

T8b949e/** Node number for the remote (destination) node. */
Tff7b72private Tff7b72const Tff7b72val Te6edf3REMOTE_NODE Tff7b72= T79c0ff2

T8b949e/** Dummy SNR value used to satisfy the snr_back requirement. */
Tff7b72private Tff7b72const Tff7b72val Te6edf3DUMMY_SNR Tff7b72= T79c0ff1T79c0ff0
Tb4b4b4}

T8b949e/**
* Creates a traceroute **request** MeshLog.
*
* @param id Packet ID used to correlate request with response.
* @param receivedDateMillis Timestamp in milliseconds.
*/
Tff7b72private Tff7b72fun Td2a8ffmakeRequestTb4b4b4(Te6edf3idTb4b4b4: Tffa657IntTb4b4b4, Te6edf3receivedDateMillisTb4b4b4: Tffa657LongTb4b4b4)Tb4b4b4: Te6edf3MeshLog Tff7b72= Te6edf3MeshLogTb4b4b4(
Te6edf3uuid Tff7b72= Ta5d6ff"Ta5d6ffreq-Tffd700$Te6edf3idTa5d6ff"Tb4b4b4,
Te6edf3message_type Tff7b72= Ta5d6ff"Ta5d6ffTRACEROUTETa5d6ff"Tb4b4b4,
Te6edf3received_date Tff7b72= Te6edf3receivedDateMillisTb4b4b4,
Te6edf3raw_message Tff7b72= Ta5d6ff"Ta5d6ff"Tb4b4b4,
Te6edf3fromRadio Tff7b72=
Te6edf3FromRadioTb4b4b4(
Te6edf3packet Tff7b72=
Te6edf3MeshPacketTb4b4b4(
Te6edf3id Tff7b72= Te6edf3idTb4b4b4,
Te6edf3from Tff7b72= Te6edf3LOCAL_NODETb4b4b4,
Te6edf3to Tff7b72= Te6edf3REMOTE_NODETb4b4b4,
Te6edf3decoded Tff7b72= Te6edf3DataTb4b4b4(Te6edf3portnum Tff7b72= Te6edf3PortNumTb4b4b4.Te6edf3TRACEROUTE_APPTb4b4b4, Te6edf3want_response Tff7b72= Tff7b72trueTb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)

T8b949e/**
* Creates a traceroute **result** MeshLog that matches a request by [requestId].
*
* @param intermediateRoute Intermediate hops on the forward path (wire format, no endpoints).
* @param intermediateRouteBack Intermediate hops on the return path (wire format, no endpoints). Pass `null` to
* omit route_back entirely (simulates no return route data).
* @param hopStart Non-zero hop_start is required (along with snr_back) for fullRouteDiscovery to wrap route_back
* with endpoints. Defaults to 3.
*/
Tff7b72private Tff7b72fun Td2a8ffmakeResultTb4b4b4(
Te6edf3requestIdTb4b4b4: Tffa657IntTb4b4b4,
Te6edf3receivedDateMillisTb4b4b4: Tffa657LongTb4b4b4,
Te6edf3intermediateRouteTb4b4b4: Te6edf3ListTff7b72<Tffa657IntTff7b72> Tff7b72= Te6edf3listOfTb4b4b4(T79c0ff3Tb4b4b4)Tb4b4b4,
Te6edf3intermediateRouteBackTb4b4b4: Te6edf3ListTff7b72<Tffa657IntTff7b72>Tff7b72? Tff7b72= Te6edf3listOfTb4b4b4(T79c0ff3Tb4b4b4)Tb4b4b4,
Te6edf3hopStartTb4b4b4: Tffa657Int Tff7b72= T79c0ff3Tb4b4b4,
Tb4b4b4)Tb4b4b4: Te6edf3MeshLog Tb4b4b4{
T8b949e// snr_back must have one entry per node in route_back for fullRouteDiscovery to wrap it
Tff7b72val Te6edf3snrBack Tff7b72= Te6edf3intermediateRouteBackTff7b72?.Te6edf3map Tb4b4b4{ Te6edf3DUMMY_SNR Tb4b4b4} Tff7b72?: Te6edf3emptyListTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3rd Tff7b72=
Te6edf3RouteDiscoveryTb4b4b4(
Te6edf3route Tff7b72= Te6edf3intermediateRouteTb4b4b4,
Te6edf3route_back Tff7b72= Te6edf3intermediateRouteBack Tff7b72?: Te6edf3emptyListTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3snr_back Tff7b72= Te6edf3snrBackTb4b4b4,
Tb4b4b4)
Tff7b72return Te6edf3MeshLogTb4b4b4(
Te6edf3uuid Tff7b72= Ta5d6ff"Ta5d6ffres-Tffd700$Te6edf3requestIdTa5d6ff"Tb4b4b4,
Te6edf3message_type Tff7b72= Ta5d6ff"Ta5d6ffTRACEROUTETa5d6ff"Tb4b4b4,
Te6edf3received_date Tff7b72= Te6edf3receivedDateMillisTb4b4b4,
Te6edf3raw_message Tff7b72= Ta5d6ff"Ta5d6ff"Tb4b4b4,
Te6edf3fromRadio Tff7b72=
Te6edf3FromRadioTb4b4b4(
Te6edf3packet Tff7b72=
Te6edf3MeshPacketTb4b4b4(
Te6edf3from Tff7b72= Te6edf3REMOTE_NODETb4b4b4,
Te6edf3to Tff7b72= Te6edf3LOCAL_NODETb4b4b4,
Te6edf3hop_start Tff7b72= Te6edf3hopStartTb4b4b4,
Te6edf3decoded Tff7b72=
Te6edf3DataTb4b4b4(
Te6edf3portnum Tff7b72= Te6edf3PortNumTb4b4b4.Te6edf3TRACEROUTE_APPTb4b4b4,
Te6edf3request_id Tff7b72= Te6edf3requestIdTb4b4b4,
Te6edf3payload Tff7b72= Te6edf3RouteDiscoveryTb4b4b4.Te6edf3ADAPTERTb4b4b4.Te6edf3encodeTb4b4b4(Te6edf3rdTb4b4b4)Tb4b4b4.Te6edf3toByteStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ffmatchesRequestToResultTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3requestTime Tff7b72= T79c0ff1T79c0ff0T79c0ff0T79c0ff0L Tff7b72* Te6edf3MS_PER_SEC
Tff7b72val Te6edf3resultTime Tff7b72= T79c0ff1T79c0ff0T79c0ff0T79c0ff5L Tff7b72* Te6edf3MS_PER_SEC
Tff7b72val Te6edf3requests Tff7b72= Te6edf3listOfTb4b4b4(Te6edf3makeRequestTb4b4b4(Te6edf3id Tff7b72= T79c0ff4T79c0ff2Tb4b4b4, Te6edf3receivedDateMillis Tff7b72= Te6edf3requestTimeTb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3results Tff7b72= Te6edf3listOfTb4b4b4(Te6edf3makeResultTb4b4b4(Te6edf3requestId Tff7b72= T79c0ff4T79c0ff2Tb4b4b4, Te6edf3receivedDateMillis Tff7b72= Te6edf3resultTimeTb4b4b4)Tb4b4b4)

Tff7b72val Te6edf3points Tff7b72= Te6edf3resolveTraceroutePointsTb4b4b4(Te6edf3requestsTb4b4b4, Te6edf3resultsTb4b4b4)

Te6edf3assertEqualsTb4b4b4(T79c0ff1Tb4b4b4, Te6edf3pointsTb4b4b4.Te6edf3sizeTb4b4b4)
Tff7b72val Te6edf3point Tff7b72= Te6edf3pointsTb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3requestsTb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3pointTb4b4b4.Te6edf3requestTb4b4b4)
Te6edf3assertNotNullTb4b4b4(Te6edf3pointTb4b4b4.Te6edf3resultTb4b4b4)
T8b949e// timeSeconds = received_date (millis) / MS_PER_SEC
Te6edf3assertEqualsTb4b4b4(T79c0ff1T79c0ff0T79c0ff0T79c0ff0.0Tb4b4b4, Te6edf3pointTb4b4b4.Te6edf3timeSecondsTb4b4b4)
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ffcomputesForwardHopsTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3requests Tff7b72= Te6edf3listOfTb4b4b4(Te6edf3makeRequestTb4b4b4(Te6edf3id Tff7b72= T79c0ff1Tb4b4b4, Te6edf3receivedDateMillis Tff7b72= T79c0ff1T79c0ff0T79c0ff0T79c0ff0L Tff7b72* Te6edf3MS_PER_SECTb4b4b4)Tb4b4b4)
T8b949e// 2 intermediate hops β†’ fullRoute = [dest, hop1, hop2, src] β†’ size 4 β†’ hops = 2
Tff7b72val Te6edf3results Tff7b72=
Te6edf3listOfTb4b4b4(
Te6edf3makeResultTb4b4b4(Te6edf3requestId Tff7b72= T79c0ff1Tb4b4b4, Te6edf3receivedDateMillis Tff7b72= T79c0ff1T79c0ff0T79c0ff0T79c0ff5L Tff7b72* Te6edf3MS_PER_SECTb4b4b4, Te6edf3intermediateRoute Tff7b72= Te6edf3listOfTb4b4b4(T79c0ff1T79c0ff0Tb4b4b4, T79c0ff2T79c0ff0Tb4b4b4)Tb4b4b4)Tb4b4b4,
Tb4b4b4)

Tff7b72val Te6edf3point Tff7b72= Te6edf3resolveTraceroutePointsTb4b4b4(Te6edf3requestsTb4b4b4, Te6edf3resultsTb4b4b4)Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)

Te6edf3assertEqualsTb4b4b4(T79c0ff2Tb4b4b4, Te6edf3pointTb4b4b4.Te6edf3forwardHopsTb4b4b4)
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ffdirectRoute_yieldsZeroHopsTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3requests Tff7b72= Te6edf3listOfTb4b4b4(Te6edf3makeRequestTb4b4b4(Te6edf3id Tff7b72= T79c0ff1Tb4b4b4, Te6edf3receivedDateMillis Tff7b72= T79c0ff1T79c0ff0T79c0ff0T79c0ff0L Tff7b72* Te6edf3MS_PER_SECTb4b4b4)Tb4b4b4)
T8b949e// Direct route: no intermediate hops β†’ fullRoute = [dest, src] β†’ size 2 β†’ hops = 0
T8b949e// route_back also empty intermediate β†’ fullRouteBack = [src, dest] β†’ size 2 β†’ hops = 0
Tff7b72val Te6edf3results Tff7b72=
Te6edf3listOfTb4b4b4(
Te6edf3makeResultTb4b4b4(
Te6edf3requestId Tff7b72= T79c0ff1Tb4b4b4,
Te6edf3receivedDateMillis Tff7b72= T79c0ff1T79c0ff0T79c0ff0T79c0ff2L Tff7b72* Te6edf3MS_PER_SECTb4b4b4,
Te6edf3intermediateRoute Tff7b72= Te6edf3emptyListTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3intermediateRouteBack Tff7b72= Te6edf3emptyListTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)

Tff7b72val Te6edf3point Tff7b72= Te6edf3resolveTraceroutePointsTb4b4b4(Te6edf3requestsTb4b4b4, Te6edf3resultsTb4b4b4)Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)

Te6edf3assertEqualsTb4b4b4(T79c0ff0Tb4b4b4, Te6edf3pointTb4b4b4.Te6edf3forwardHopsTb4b4b4)
T8b949e// route_back with empty intermediateRouteBack: snr_back will be empty,
T8b949e// so fullRouteDiscovery won't wrap it β†’ raw route_back is empty β†’ returnHops = null
Te6edf3assertNullTb4b4b4(Te6edf3pointTb4b4b4.Te6edf3returnHopsTb4b4b4)
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ffcomputesRoundTripSecondsTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3requestTime Tff7b72= T79c0ff2T79c0ff0T79c0ff0T79c0ff0L Tff7b72* Te6edf3MS_PER_SEC T8b949e// 2_000_000 ms
Tff7b72val Te6edf3resultTime Tff7b72= Te6edf3requestTime Tff7b72+ T79c0ff3T79c0ff5T79c0ff0T79c0ff0L T8b949e// 3.5 seconds later in millis
Tff7b72val Te6edf3requests Tff7b72= Te6edf3listOfTb4b4b4(Te6edf3makeRequestTb4b4b4(Te6edf3id Tff7b72= T79c0ff1Tb4b4b4, Te6edf3receivedDateMillis Tff7b72= Te6edf3requestTimeTb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3results Tff7b72= Te6edf3listOfTb4b4b4(Te6edf3makeResultTb4b4b4(Te6edf3requestId Tff7b72= T79c0ff1Tb4b4b4, Te6edf3receivedDateMillis Tff7b72= Te6edf3resultTimeTb4b4b4)Tb4b4b4)

Tff7b72val Te6edf3point Tff7b72= Te6edf3resolveTraceroutePointsTb4b4b4(Te6edf3requestsTb4b4b4, Te6edf3resultsTb4b4b4)Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)

Tff7b72val Te6edf3rtt Tff7b72= Te6edf3assertNotNullTb4b4b4(Te6edf3pointTb4b4b4.Te6edf3roundTripSecondsTb4b4b4)
Te6edf3assertEqualsTb4b4b4(T79c0ff3.5Tb4b4b4, Te6edf3rttTb4b4b4, T79c0ff0.01Tb4b4b4)
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ffnoMatchingResult_yieldsNullsTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3requests Tff7b72= Te6edf3listOfTb4b4b4(Te6edf3makeRequestTb4b4b4(Te6edf3id Tff7b72= T79c0ff1Tb4b4b4, Te6edf3receivedDateMillis Tff7b72= T79c0ff1T79c0ff0T79c0ff0T79c0ff0L Tff7b72* Te6edf3MS_PER_SECTb4b4b4)Tb4b4b4)
T8b949e// Result has a different requestId, so it won't match
Tff7b72val Te6edf3results Tff7b72= Te6edf3listOfTb4b4b4(Te6edf3makeResultTb4b4b4(Te6edf3requestId Tff7b72= T79c0ff9T79c0ff9Tb4b4b4, Te6edf3receivedDateMillis Tff7b72= T79c0ff1T79c0ff0T79c0ff0T79c0ff5L Tff7b72* Te6edf3MS_PER_SECTb4b4b4)Tb4b4b4)

Tff7b72val Te6edf3point Tff7b72= Te6edf3resolveTraceroutePointsTb4b4b4(Te6edf3requestsTb4b4b4, Te6edf3resultsTb4b4b4)Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)

Te6edf3assertNullTb4b4b4(Te6edf3pointTb4b4b4.Te6edf3resultTb4b4b4)
Te6edf3assertNullTb4b4b4(Te6edf3pointTb4b4b4.Te6edf3forwardHopsTb4b4b4)
Te6edf3assertNullTb4b4b4(Te6edf3pointTb4b4b4.Te6edf3returnHopsTb4b4b4)
Te6edf3assertNullTb4b4b4(Te6edf3pointTb4b4b4.Te6edf3roundTripSecondsTb4b4b4)
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ffemptyInputs_returnsEmptyTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3assertEqualsTb4b4b4(Te6edf3emptyListTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3resolveTraceroutePointsTb4b4b4(Te6edf3emptyListTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3emptyListTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4)
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ffmultipleRequests_preservesOrderTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3req1 Tff7b72= Te6edf3makeRequestTb4b4b4(Te6edf3id Tff7b72= T79c0ff1Tb4b4b4, Te6edf3receivedDateMillis Tff7b72= T79c0ff3T79c0ff0T79c0ff0T79c0ff0L Tff7b72* Te6edf3MS_PER_SECTb4b4b4)
Tff7b72val Te6edf3req2 Tff7b72= Te6edf3makeRequestTb4b4b4(Te6edf3id Tff7b72= T79c0ff2Tb4b4b4, Te6edf3receivedDateMillis Tff7b72= T79c0ff4T79c0ff0T79c0ff0T79c0ff0L Tff7b72* Te6edf3MS_PER_SECTb4b4b4)
Tff7b72val Te6edf3res1 Tff7b72= Te6edf3makeResultTb4b4b4(Te6edf3requestId Tff7b72= T79c0ff1Tb4b4b4, Te6edf3receivedDateMillis Tff7b72= T79c0ff3T79c0ff0T79c0ff0T79c0ff5L Tff7b72* Te6edf3MS_PER_SECTb4b4b4)
Tff7b72val Te6edf3res2 Tff7b72= Te6edf3makeResultTb4b4b4(Te6edf3requestId Tff7b72= T79c0ff2Tb4b4b4, Te6edf3receivedDateMillis Tff7b72= T79c0ff4T79c0ff0T79c0ff0T79c0ff5L Tff7b72* Te6edf3MS_PER_SECTb4b4b4)

Tff7b72val Te6edf3points Tff7b72= Te6edf3resolveTraceroutePointsTb4b4b4(Te6edf3listOfTb4b4b4(Te6edf3req1Tb4b4b4, Te6edf3req2Tb4b4b4)Tb4b4b4, Te6edf3listOfTb4b4b4(Te6edf3res1Tb4b4b4, Te6edf3res2Tb4b4b4)Tb4b4b4)

Te6edf3assertEqualsTb4b4b4(T79c0ff2Tb4b4b4, Te6edf3pointsTb4b4b4.Te6edf3sizeTb4b4b4)
Te6edf3assertEqualsTb4b4b4(T79c0ff3T79c0ff0T79c0ff0T79c0ff0.0Tb4b4b4, Te6edf3pointsTff7b72[T79c0ff0Tff7b72]Tb4b4b4.Te6edf3timeSecondsTb4b4b4)
Te6edf3assertEqualsTb4b4b4(T79c0ff4T79c0ff0T79c0ff0T79c0ff0.0Tb4b4b4, Te6edf3pointsTff7b72[T79c0ff1Tff7b72]Tb4b4b4.Te6edf3timeSecondsTb4b4b4)
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ffemptyRouteBack_yieldsNullReturnHopsTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3requests Tff7b72= Te6edf3listOfTb4b4b4(Te6edf3makeRequestTb4b4b4(Te6edf3id Tff7b72= T79c0ff1Tb4b4b4, Te6edf3receivedDateMillis Tff7b72= T79c0ff1T79c0ff0T79c0ff0T79c0ff0L Tff7b72* Te6edf3MS_PER_SECTb4b4b4)Tb4b4b4)
T8b949e// 1 intermediate hop forward, but null route_back β†’ no return path data
Tff7b72val Te6edf3results Tff7b72=
Te6edf3listOfTb4b4b4(
Te6edf3makeResultTb4b4b4(
Te6edf3requestId Tff7b72= T79c0ff1Tb4b4b4,
Te6edf3receivedDateMillis Tff7b72= T79c0ff1T79c0ff0T79c0ff0T79c0ff5L Tff7b72* Te6edf3MS_PER_SECTb4b4b4,
Te6edf3intermediateRoute Tff7b72= Te6edf3listOfTb4b4b4(T79c0ff3Tb4b4b4)Tb4b4b4,
Te6edf3intermediateRouteBack Tff7b72= Tff7b72nullTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)

Tff7b72val Te6edf3point Tff7b72= Te6edf3resolveTraceroutePointsTb4b4b4(Te6edf3requestsTb4b4b4, Te6edf3resultsTb4b4b4)Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)

Te6edf3assertEqualsTb4b4b4(T79c0ff1Tb4b4b4, Te6edf3pointTb4b4b4.Te6edf3forwardHopsTb4b4b4)
Te6edf3assertNullTb4b4b4(Te6edf3pointTb4b4b4.Te6edf3returnHopsTb4b4b4)
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ffreturnHops_computedWhenRouteBackAvailableTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3requests Tff7b72= Te6edf3listOfTb4b4b4(Te6edf3makeRequestTb4b4b4(Te6edf3id Tff7b72= T79c0ff1Tb4b4b4, Te6edf3receivedDateMillis Tff7b72= T79c0ff1T79c0ff0T79c0ff0T79c0ff0L Tff7b72* Te6edf3MS_PER_SECTb4b4b4)Tb4b4b4)
T8b949e// 1 intermediate hop on return path, with hop_start and snr_back set
T8b949e// β†’ fullRouteBack = [src, hop, dest] β†’ size 3 β†’ returnHops = 1
Tff7b72val Te6edf3results Tff7b72=
Te6edf3listOfTb4b4b4(
Te6edf3makeResultTb4b4b4(
Te6edf3requestId Tff7b72= T79c0ff1Tb4b4b4,
Te6edf3receivedDateMillis Tff7b72= T79c0ff1T79c0ff0T79c0ff0T79c0ff5L Tff7b72* Te6edf3MS_PER_SECTb4b4b4,
Te6edf3intermediateRoute Tff7b72= Te6edf3listOfTb4b4b4(T79c0ff3Tb4b4b4)Tb4b4b4,
Te6edf3intermediateRouteBack Tff7b72= Te6edf3listOfTb4b4b4(T79c0ff3Tb4b4b4)Tb4b4b4,
Te6edf3hopStart Tff7b72= T79c0ff3Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)

Tff7b72val Te6edf3point Tff7b72= Te6edf3resolveTraceroutePointsTb4b4b4(Te6edf3requestsTb4b4b4, Te6edf3resultsTb4b4b4)Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)

Te6edf3assertEqualsTb4b4b4(T79c0ff1Tb4b4b4, Te6edf3pointTb4b4b4.Te6edf3forwardHopsTb4b4b4)
Te6edf3assertEqualsTb4b4b4(T79c0ff1Tb4b4b4, Te6edf3pointTb4b4b4.Te6edf3returnHopsTb4b4b4)
Tb4b4b4}
Tb4b4b4}

Served by rngit 1.5.0 - Generated in 0.12s